package test.bytes;

import static org.hamcrest.CoreMatchers.nullValue;

import java.io.UnsupportedEncodingException;

import org.junit.Test;

import com.sun.org.apache.bcel.internal.generic.NEW;

import javafx.beans.binding.StringBinding;
import jdk.nashorn.internal.ir.ReturnNode;
import sun.tools.jar.resources.jar;

/**
 * 将一种编码的字节数组转换成另一种编码的字节数组
 * @author 风蚕
 *
 */
public class encodeChange {
	
	
	@Test
	public void test() throws Exception {
		byte[] utf16 = unicodeToUtf16Byte(0x20003);
		System.out.println("打印二进制字符串。。。");
		System.out.println(bytesToBinaryString(utf16));
		System.out.println(new String(utf16));
	}
	
	@Test
	public void testRun() throws Exception {
		//11011000_01000000_11011100_00000011
		// 0x20003是𠀃的unicode编码
//		System.out.println(bytesToBinaryString(unicodeToUtf16Byte(0x20003)));
		
		String word = new String(unicodeToUtf16Char(0x20003));
		byte[] utf16 = word.getBytes("utf-16");
		System.out.println(bytesToBinaryString(utf16));
//		byte[] utf8 = word.getBytes("utf-8");
//		System.out.println(bytesToBinaryString(utf8));
//		char c = '中';
//		System.out.println(new Integer(c).toBinaryString(c));
//		byte[] utf8 = "中".getBytes("utf-8");
//		System.out.println(bytesToBinaryString(utf8));
//		byte[] gbk = "中".getBytes("gbk");
//		System.out.println(bytesToBinaryString(gbk));
		
//		for(byte b : b1s) {
//			System.out.println(b);
//			System.out.println(Integer.toBinaryString(b));
//			System.out.println(byteToBinaryString(b));
//		}
		
//		System.out.println(word);
//		System.out.println(new String(word.getBytes("utf-16")));
//		System.out.println(new String(unicodeToUtf16Byte(0x20003)));
	}
	/**
	 * 将unicode编码转化成utf16编码字节
	 * 转码规则：
	 * 1、unicode码0x0000~0xffff范围内的字符，不转化，使用连个byte（一个char）表示
	 * 2、unicode码0x10000~0x10ffff范围的字符，使用4个byte（2个char）表示
	 * a、先将unicode减去0x10000
	 * b、再写成20个bit的二进制码，xxxx_xxxxxxyy_yyyyyyyy
	 * c、前10位前加110110，后10位前加110111，组成一个4个byte的二进制
	 * @param unicode
	 * @return
	 */
	public char[] unicodeToUtf16Char(int unicode) {
		
		//1、先减去0x10000
		int unicodeCut = unicode - 0x10000;
		//2、转化成二进制字符串
		String binaryStr = Integer.toBinaryString(unicodeCut);
		//3、二进制字符串补零，20个bit
		binaryStr = addZero(binaryStr);
		//4、拼装成4个byte的二进制
		String highStr = "110110" + binaryStr.substring(0, 10);
		String lowStr = "110111" + binaryStr.substring(10);
		char[] chars = new char[2];
		chars[0] = (char)(int)Integer.valueOf(highStr, 2);
		chars[1] = (char)(int)Integer.valueOf(lowStr, 2);
		return chars;
		
	}
	/**
	 * 将unicode编码转化成字节数组
	 * @param unicode
	 * @return
	 * @throws Exception
	 */
	public byte[] unicodeToUtf16Byte(int unicode) throws Exception {
		//1、先减去0x10000
		int unicodeCut = unicode - 0x10000;
		//2、转化成二进制字符串
		String binaryStr = Integer.toBinaryString(unicodeCut);
		//3、二进制字符串补零，20个bit
		binaryStr = addZero(binaryStr);
		//4、拼装成4个byte的二进制
		String highStr = "110110" + binaryStr.substring(0, 10);
		String lowStr = "110111" + binaryStr.substring(10);
		String utf16BinaryStr = highStr + lowStr;
		byte[] utf16Bytes;
		utf16Bytes = new byte[4];
		utf16Bytes[0] = valueOfByte(utf16BinaryStr.substring(0, 8), 2);
		utf16Bytes[1] = valueOfByte(utf16BinaryStr.substring(8, 16), 2);
		utf16Bytes[2] = valueOfByte(utf16BinaryStr.substring(16, 24), 2);
		utf16Bytes[3] = valueOfByte(utf16BinaryStr.substring(24, 32), 2);
		return utf16Bytes;
	}
	
	/**
	 * 其他进制字符串转换成byte类型
	 * @param s 需要转换的字符串
	 * @param radix 指定字符串的进制
	 * @return
	 * @throws Exception 
	 */
	public byte valueOfByte(String s,int radix) throws Exception {
		int a = Integer.valueOf(s, radix);
		if(a >255) {
			throw new Exception("字符串超出八位");
		}
		//负数计算规则：补码+1，再加负号
		a = -((a^0b11111111) + 1);
		return (byte) a;
	}
	
	/**
	 * 将byte类型的数字转换成长度为8的二进制字符串
	 * @param b
	 * @return
	 */
	public String byteToBinaryString(byte b) {
		if(b<0) {
			return Integer.toBinaryString(b).substring(24);
		}
		String binaryStr = Integer.toBinaryString(b);
		int length = binaryStr.length();
		if(length==8) {
			return binaryStr;
		}
		
		for (int i = 0; i < 8-length; i++) {
			binaryStr = "0" + binaryStr;
		}
		return binaryStr;
		
	}
	/**
	 * 字节数组转换成二进制字符串
	 * @param bs
	 * @return
	 */
	public String bytesToBinaryString(byte[] bs) {
		StringBuilder str = new StringBuilder();
		for(byte b : bs) {
			str.append(byteToBinaryString(b));
		}
		return str.toString();
	}
	
	/**
	 * 二进制补零
	 * @param binaryStr
	 * @return
	 */
	public String addZero(String binaryStr) {
		if(binaryStr.length()<=20) {
			int addZero = 20 - binaryStr.length();
			for(int i=0;i<addZero;i++) {
				binaryStr = "0"+binaryStr;
			}
			return binaryStr;
		}else {
			return null;
		}
	}
}
